/*	Grua 

        C.A.D. 						Curso 2011-2012
 	
	Codigo base para la realización de las practicas de CAD

	modulo modelo.c
	Dibujo del modelo
=======================================================

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details 
 http://www.gnu.org/copyleft/gpl.html

=======================================================
Queda prohibido cobrar canon por la copia de este software

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>                   // Libreria de utilidades de OpenGL

#define __modelo__			// Hace que se asigne memoria a las variables globales

#include "castles.h"



int COLORGRUA=0;


/**	void initModel()

Inicializa el modelo y de las variables globales

**/

void initModel()
{

/**
Definicion de los colores usados.
**/
float colores[9][4]={{1,1,0,1.},{0.7,0.7,0.7,1},{1.0,0.3,0.3,1},
   		   {0.7,0.6,0.2,1},{0.2,1.0,1.0,1},{1.0,0.86,0.3,1},
                     {0.4,1,0.4,1.},{1,0.6,1,1.},{0,0,1,1.}};
int i,j,k;
	for(i=0;i<4;++i)
		for(j=0;j<9;++j)
			color[j][i]=colores[j][i];

/**
Gravedad
**/
    gravedad=9.8;

/**
Turno Inicial
**/
    turno=0;

/**
BloqueBase
**/
    bloqueBase.Xdim=2;
    bloqueBase.Ydim=2;
    bloqueBase.Zdim=2;
    bloqueBase.masa=10;


/**
Jugadores
**/
    //Jugador0 --> Rojo
    jugadores[0].nJugador=0;
    jugadores[0].color[0]=0.9;  //R
    jugadores[0].color[1]=0.1;  //G
    jugadores[0].color[2]=0.1;  //B
    inicJugador(&jugadores[0]);
    //Jugador1 --> Amarillo
    jugadores[1].nJugador=1;
    jugadores[1].color[0]=0.9;  //R
    jugadores[1].color[1]=0.9;  //G
    jugadores[1].color[2]=0.1;  //B
    inicJugador(&jugadores[1]);



/**
Parametros iniciales de la camara
**/
    // Angulos de rotacion
    view_rotx=35.0;
    view_roty=-90.0;
    view_rotz=0.0;
    d=100.0;

    // Posicion de la camara
    x_camara=jugadores[turno].proy.xInic+10;
    y_camara=jugadores[turno].proy.yInic+10;
    z_camara=jugadores[turno].proy.zInic;

    VISTA_PERSPECTIVA=1;	// Flag perspectiva/paralela

    ventanaMundoParalela=150;	// Ventana para proyeccion paralela
    origenXVentanaMundoParalelo=0;
    origenYVentanaMundoParalelo=0;

/**
Materiales
**/
    // Propiedades de la luz
    mat_specular[3]=mat_specular[2]=mat_specular[1]=mat_specular[0]=1.0;
    // Brillo de la superficie
    mat_shininess[0]= 50.0;
    // Posición de la luz
    light_position[0] = 5.0;
    light_position[1] = 5.0;
    light_position[2] = 10.0;
    light_position[3] = 0.0;
}



/**	void Dibuja( void )

Procedimiento de dibujo del modelo. Es llamado por glut cada vez que se debe redibujar.

**/

void Dibuja( void )
{
    glInitNames();
    glPushName(-1);


    glPushMatrix();
    // Fija el color de fondo a azul
    glClearColor(0,0,0.6,1);
    // Inicializa el buffer de color
    glClear( GL_COLOR_BUFFER_BIT  | GL_DEPTH_BUFFER_BIT );
    // Carga transformacion de visualizacion
    transformacionVisualizacion();
    // Set light properties
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    ejes(3);



    glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);    // Enable color
    glEnable(GL_LIGHTING);          // Enable lighting for surfaces
    glEnable(GL_LIGHT0);            // Enable light source
    glEnable(GL_DEPTH_TEST);        // Enable depth buffering
    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    /* Propieadades de luz y material */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
    glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);

    /* Suelo */
    glColor3f(0.1,0.9,0);
    glShadeModel( GL_SMOOTH );
    glTranslatef(0,-0.5,0);
    caja(200,0.5,200);
    glTranslatef(0,+0.5,0);



    int trans=10;
    glTranslatef(trans/2,0,0);
    dibujaJugador(&jugadores[0]);

    glRotatef(180,0,1,0);
    glTranslatef(trans,0,0);

    dibujaJugador(&jugadores[1]);    


    glPopMatrix(); 		// Desapila la transformacion geometrica
    glutSwapBuffers();	// Intercambia el buffer de dibujo y visualizacion

}


/**	void idle()

Procedimiento de fondo. Es llamado por glut cuando no hay eventos pendientes.

**/
void idle()
{
    actualizaProyectil(&(jugadores[turno].proy));
    float disAux=20;

    if(turno==0){
        // Angulos de rotacion
        view_rotx=35.0;
        view_roty=-90.0+jugadores[turno].proy.angY;
        view_rotz=0.0;
        d=100.0;

        // Posicion de la camara
        if(!jugadores[turno].proy.disparado){
            x_camara=jugadores[turno].proy.xInic+disAux;
            y_camara=jugadores[turno].proy.yInic+10;
            z_camara=jugadores[turno].proy.zInic;
        }else{
            x_camara=jugadores[turno].proy.x+disAux;
            y_camara=jugadores[turno].proy.y+10;
            z_camara=jugadores[turno].proy.z;
        }
    }else{
        // Angulos de rotacion
        view_rotx=35.0;
        view_roty=-270+jugadores[turno].proy.angY;
        view_rotz=0.0;
        d=100.0;

        // Posicion de la camara
        if(!jugadores[turno].proy.disparado){
            x_camara=-(jugadores[turno].proy.xInic+disAux);
            y_camara=jugadores[turno].proy.yInic+10;
            z_camara=-jugadores[turno].proy.zInic;
        }else{
            x_camara=-(jugadores[turno].proy.x+disAux);
            y_camara=jugadores[turno].proy.y+10;
            z_camara=-jugadores[turno].proy.z;

        }
    }

 gluiPostRedisplay();			// Redibuja
 glutTimerFunc(30,idle,0);		// Vuelve a lanzar otro evento de redibujado en 30 ms
}

/**
    Función Pick
**/
int pick(int x, int y)
{
    GLint buff[512];
    glSelectBuffer(512, buff); //Indicamos que buff es la variable a usar como buffer de selección
    GLint viewport[4];
    GLint hits;

    glRenderMode(GL_SELECT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glGetIntegerv(GL_VIEWPORT, viewport);

    //Tamaño de ventana de selección de 5x5
    gluPickMatrix(x,viewport[3]-y,5,5, viewport);
    fijaProyeccion();
    Dibuja();

    //Tras todo esto, se deja la matriz de proyección como estaba
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    fijaProyeccion();

    //Hits contiene el nº de objetos que han caido en la seleccion
    hits=glRenderMode(GL_RENDER);

    int i, aux=-1;
    float zmin, zmax, cercana=-1;

    for (i=0; i< hits*4; i+=4)
    {
        zmin=-1*(float)buff[i+1]/0xFFFFFFFF; //zmax=-1*(float)buff[i+2]/0xFFFFFFFF;
        if(buff[i+3]!=-1 && zmin>cercana)
        {
            cercana=zmin;
            aux=buff[i+3];
        }
    }
    return aux;
}

